﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BeachRunner.Utility
{
    /// <summary>
    /// AnimationSet ist eine Klasse um mehrere zusammengehörige Animationen zu realisieren
    /// 
    /// Autor: OLD (Mattis Hänel)
    /// </summary>
    public class AnimationSet
    {
        /// <summary>
        /// Alle Animationsframes werden in diesem spriteSet gehalten.
        /// </summary>
        private SpriteSet spriteSet;
        /// <summary>
        /// Macht die Grafik der Animationsframes zugänglich.
        /// </summary>
        public Texture2D Texture
        {
            get { return spriteSet.Texture; }
        }
        /// <summary>
        /// Macht die Rectangles der Aniamtionsframes zugänglich.
        /// </summary>
        public Rectangle CurrentRectangle
        {
            get { return spriteSet.Rect[animationIndex[currentAnimation][currentFrame]]; }
        }

        /// <summary>
        /// Gibt an ob eine Animation gerade läuft.
        /// </summary>
        private bool runs = false;
        /// <summary>
        /// Gibt an ob eine Animation gerade läuft.
        /// </summary>
        public bool IsRunning()
        {
            return runs;
        }

        /// <summary>
        /// Gibt an ob eine bestimmte Aniamtion gerade läuft
        /// </summary>
        /// <param name="animationId"></param>
        /// <returns></returns>
        public bool IsRunning(int animationId)
        {
            return currentAnimation == animationId & runs;
        }

        /// <summary>
        /// Gibt an ob die Animation nach Ablauf neu beginnt.
        /// </summary>
        private bool loop = true;
            
        /// <summary>
        /// Gibt an ob die Animation nach Ablauf neu beginnt.
        /// </summary>
        public bool IsLooping
        {
            get { return loop; }
            set { loop = value; }
        }
 
        /// <summary>
        /// Speichert für jedes Frame (zweiter Index) einer Animation (erster Index) das zugehörige Frame
        /// in der Animationsgrafik
        /// </summary>
        private short[][] animationIndex;
        /// <summary>
        /// Speichert für jedes Frame (zweiter Index) einer Animation (erster Index) die zugehörige Dauer
        /// in Millisekunden.
        /// </summary>
        private short[][] animationTime;

        /// <summary>
        /// Hält die Animationsgeschwindigkeit.
        /// z.B.    timeScale = 1.0 normale Geschwindigkeit
        ///         timeScale = 2.0 doppelte Geschwindigkeit
        ///         timeScale = 0.5 halbe Geschwindigkeit
        /// </summary>
        private double timeScale = 1.0;
        /// <summary>
        /// Zum anpassen der Animationsgeschwindigkeit.
        /// z.B.    timeScale = 1.0 normale Geschwindigkeit
        ///         timeScale = 2.0 doppelte Geschwindigkeit
        ///         timeScale = 0.5 halbe Geschwindigkeit
        /// </summary>
        public double TimeScale
        {
            get { return 1 / timeScale; }
            set { timeScale = 1 / value; }
        }

        /// <summary>
        /// Gibt die momentan gewählte Aniamtion an.
        /// </summary>
        private int currentAnimation;
        public int AnimationID
        {
            get { return currentAnimation; }
            set
            {
                currentAnimation = value;
                currentFrame = 0;
            }
        }

        /// <summary>
        /// Gibt das momentan angezeigte Frame der Animation an.
        /// </summary>
        private int currentFrame;

        public int FrameID
        {
            get { return currentFrame; }
            set { currentFrame = value; }
        }

        /// <summary>
        /// Macht die Anzahl der in der momentanen Animation enhaltenen Frames zugänglich.
        /// </summary>
        public int Frames
        {
            get { return animationIndex[currentAnimation].Length; }
        }

        /// <summary>
        /// Gibt an wie viele Millisekuden das momentane Frame noch dauert.
        /// </summary>
        private int timeLeft;

        /// <summary>
        /// Erstellt ein neues AnimationsSet.
        /// </summary>
        /// <param name="texture">Die Grafik die für die Animationen verwendet werden soll.</param>
        public AnimationSet(Texture2D texture, int frameWidth, int frameHeight, short[][] indexes, short[][] times )
        {
            animationIndex = indexes;
            animationTime = times;

            spriteSet = new SpriteSet(texture, frameWidth, frameHeight);
        }

        /// <summary>
        /// Erstellt ein neues AnimationsSet.
        /// </summary>
        /// <param name="spriteSet">Die Grafik die für die Animationen verwendet werden soll.</param>
        public AnimationSet(SpriteSet spriteSet, short[][] indexes, short[][] times)
        {
            animationIndex = indexes;
            animationTime = times;

            this.spriteSet = spriteSet;
        }

        /// <summary>
        /// Erstellt ein neues AnimationsSet ( Kopierkonstruktor ).
        /// </summary>
        /// <param name="spriteSet">Die Grafik die für die Animationen verwendet werden soll.</param>
        public AnimationSet( AnimationSet animationSet )
        {
            animationIndex = animationSet.animationIndex;
            animationTime = animationSet.animationTime;

            this.spriteSet = animationSet.spriteSet;
        }

        /// <summary>
        /// Aktualisiert die Animation
        /// </summary>
        public void Update()
        {
            if (runs)
            {
                timeLeft -= Game1.TIME_PER_TICK;

                if (timeLeft <= 0)
                {
                    currentFrame++;
                    if (currentFrame >= animationIndex[currentAnimation].Length)
                    {
                        currentFrame = 0;
                        if (!loop)
                        {
                            StopAnimation();
                        }
                    }
                    timeLeft = (short)(animationTime[currentAnimation][currentFrame] * timeScale);
                }
            }
        }

        /// <summary>
        /// Startet die momentane Animation.
        /// </summary>
        public void PlayAnimation()
        {
            runs = true;
        }

        /// <summary>
        /// Pausiert die momentane Animation
        /// </summary>
        public void PauseAnimation()
        {
            runs = false;
        }

        /// <summary>
        /// Stopt die momentane Animation, und setzt sie auf das erste Frame zurück.
        /// </summary>
        public void StopAnimation()
        {
            currentFrame = 0;
            runs = false;
        }
    }
}
